{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "f8415c3d",
   "metadata": {},
   "source": [
    "1. 协变和逆变是用来修饰泛型的,协变 out,逆变 in\n",
    "2. 协变和逆变用在泛型中,修饰泛型字母的,只有泛型接口和泛型委托能使用.\n",
    "3. 协变和逆变的作用:用out修饰的泛型,只能作为返回值;用in修饰的泛型 只能作为参数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "81301fe9",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Father method called\r\n"
     ]
    }
   ],
   "source": [
    "delegate T CovariantDelegate<out T>(); //T只能作为返回值,不能用作参数\n",
    "\n",
    "delegate void ContravariantDelegate<in T>(T arg); //T只能作为参数,不能用作返回值\n",
    "\n",
    "class Father{\n",
    "\n",
    "}\n",
    "\n",
    "class Son : Father{\n",
    "\n",
    "}\n",
    "\n",
    "//协变:父类装子类(里氏替换原则)\n",
    "CovariantDelegate<Son> sonDelegate = () => new Son();\n",
    "CovariantDelegate<Father> fatherDelegate = sonDelegate; //父类可以替换子类\n",
    "Father father = fatherDelegate(); //调用时返回子类对象,父类指向子类\n",
    "\n",
    "//逆变:子类装父类\n",
    "ContravariantDelegate<Father> fatherContravariantDelegate = (Father f) => { Console.WriteLine(\"Father method called\"); };\n",
    "ContravariantDelegate<Son> sonContravariantDelegate = fatherContravariantDelegate; //父类可以替换子类\n",
    "sonContravariantDelegate(new Son()); //调用时传入子类对象,父类指向子类,实际上调用的是父类的方法"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": ".NET (C#)",
   "language": "C#",
   "name": ".net-csharp"
  },
  "language_info": {
   "name": "polyglot-notebook"
  },
  "polyglot_notebook": {
   "kernelInfo": {
    "defaultKernelName": "csharp",
    "items": [
     {
      "aliases": [],
      "name": "csharp"
     }
    ]
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
